/*
 *    Copyright (c) 2018-2025, boss All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the boss developer nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * Author: boss
 */
package com.hopes.bizz.poll.pollwqi.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hopes.bizz.common.core.util.DateUtils;
import com.hopes.bizz.poll.common.constant.MonitorConstant;
import com.hopes.bizz.poll.common.constant.OmConstant;
import com.hopes.bizz.poll.common.constant.PollFactorConstant;
import com.hopes.bizz.poll.factor.entity.PollFactorInfoEntity;
import com.hopes.bizz.poll.factor.service.PollFactorInfoService;
import com.hopes.bizz.poll.monitor.entity.PollMonitorSiteEntity;
import com.hopes.bizz.poll.monitor.service.PollMonitorSiteService;
import com.hopes.bizz.poll.om.dto.PollRtDataDTO;
import com.hopes.bizz.poll.om.entity.BaseOmDataEntity;
import com.hopes.bizz.poll.om.entity.PollHourEntity;
import com.hopes.bizz.poll.om.entity.PollMinEntity;
import com.hopes.bizz.poll.om.entity.PollRtDataHisEntity;
import com.hopes.bizz.poll.om.service.PollHourService;
import com.hopes.bizz.poll.om.service.PollMinService;
import com.hopes.bizz.poll.om.service.PollRtDataHisService;
import com.hopes.bizz.poll.pollaqi.entity.Aqi;
import com.hopes.bizz.poll.pollwqi.entity.PollWqiDataEntity;
import com.hopes.bizz.poll.pollwqi.entity.PollWqiEntity;
import com.hopes.bizz.poll.pollwqi.mapper.PollWqiDataMapper;
import com.hopes.bizz.poll.pollwqi.service.PollWqiDataService;
import com.hopes.bizz.poll.pollwqi.service.PollWqiService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 	WQI数据计算
 *
 * @author cx
 * @date 2023-10-16 13:03:00
 */
@Service
public class PollWqiDataServiceImpl extends ServiceImpl<PollWqiDataMapper, PollWqiDataEntity> implements PollWqiDataService {

    @Autowired
    private PollWqiService pollWqiService;
    @Autowired
    private PollMonitorSiteService pollMonitorSiteService;
    @Autowired
    private PollRtDataHisService pollRtDataHisService;
    @Autowired
    private PollFactorInfoService pollFactorInfoService;
    @Autowired
    private PollHourService pollHourService;
    @Autowired
    private PollMinService pollMinService;

    @Override
    public JSONObject getDayDate() {
        // 获取当月日期list
        List<String> timeList = DateUtils.getDayListOfMonth();
        LambdaQueryWrapper<PollWqiDataEntity> query = Wrappers.lambdaQuery();
        query.eq(PollWqiDataEntity::getDataType, OmConstant.DATA_TYPE_DAY);
        query.ge(PollWqiDataEntity::getDataTime, timeList.get(0)).le(PollWqiDataEntity::getDataTime, timeList.get(timeList.size() - 1));
        List<PollWqiDataEntity> pollWqiDataEntities = baseMapper.selectList(query);
        JSONObject res = new JSONObject();
        List<Integer> data = Stream.generate(() -> 0).limit(timeList.size()).collect(Collectors.toList());
        for (PollWqiDataEntity pollWqiDataEntity : pollWqiDataEntities) {
            int index = timeList.indexOf(pollWqiDataEntity.getDataTimeStr());
            data.set(index, pollWqiDataEntity.getDataJson().getJSONObject(OmConstant.WQI).getInteger(OmConstant.VAL));
        }
        res.put("time", timeList);
        res.put("data", data);
        res.put("WQIList", pollWqiService.list());
        return res;
    }

    @Override
    public Boolean calculateWQIRtHandler(Long monitorSiteId) {
        // 查询WQI站点
        ArrayList<Long> monitorSiteList = new ArrayList<>();
        monitorSiteList.add(monitorSiteId);
        PollRtDataDTO pollRtDataDTO = new PollRtDataDTO();
        pollRtDataDTO.setIdList(monitorSiteList);
        List<PollRtDataHisEntity> pollRtDataHisEntities = pollRtDataHisService.queryByTimeAndMonitorList(pollRtDataDTO);
        if (CollectionUtil.isEmpty(pollRtDataHisEntities)){
            // 数据为空直接返回
            return true;
        }
        else {
            int index = pollRtDataHisEntities.size() - 1;
            ArrayList<PollRtDataHisEntity> selectList = new ArrayList<>();
            selectList.add(pollRtDataHisEntities.get(index));
            JSONObject sumO = new JSONObject();
            Double wqiValue = getWqiValue(selectList, sumO);
            // 保存数据
            saveWQI(sumO, wqiValue, new Date(), OmConstant.DATA_TYPE_RT);
            return true;
        }
    }


    @Override
    public Boolean calculateWQIMinHandler() {
        // 查询WQI站点
        LambdaQueryWrapper<PollMonitorSiteEntity> wrapper = new LambdaQueryWrapper<>();
        List<Long> monitorSiteList = pollMonitorSiteService.list(wrapper)
                .stream()
                .map(PollMonitorSiteEntity::getId)
                .distinct().collect(Collectors.toList());
        if (CollectionUtil.isEmpty(monitorSiteList)) {
            // 没有WQI站点直接返回
            return true;
        }
        Calendar cal = Calendar.getInstance();
        Date endTime = cal.getTime();
        cal.add(Calendar.MINUTE, -10);
        Date beginTime = cal.getTime();
        PollRtDataDTO pollRtDataDTO = new PollRtDataDTO();
        pollRtDataDTO.setBeginTime(beginTime);
        pollRtDataDTO.setEndTime(endTime);
        pollRtDataDTO.setIdList(monitorSiteList);
        List<PollRtDataHisEntity> pollRtDataHisEntities = pollRtDataHisService.queryByTimeAndMonitorList(pollRtDataDTO);
        if (CollectionUtil.isEmpty(pollRtDataHisEntities)){
            // 数据为空直接返回
            return true;
        }
        JSONObject sumO = new JSONObject();
            Double wqiValue = getWqiValue(pollRtDataHisEntities, sumO);

        // 保存数据
        saveWQI(sumO, wqiValue, new Date(), OmConstant.DATA_TYPE_MIN);

        return true;
    }

    public Boolean calculateWQIDayHandler() {
        // 查询WQI站点
        LambdaQueryWrapper<PollMonitorSiteEntity> wrapper = new LambdaQueryWrapper<>();
        List<Long> monitorSiteList = pollMonitorSiteService.list(wrapper)
                .stream()
                .map(PollMonitorSiteEntity::getId)
                .distinct().collect(Collectors.toList());
        if (CollectionUtil.isEmpty(monitorSiteList)) {
            // 没有WQI站点直接返回
            return true;
        }
        Calendar cal = Calendar.getInstance();
        Date endTime = cal.getTime();
        cal.add(Calendar.DAY_OF_YEAR, -1);
        Date beginTime = cal.getTime();
        PollRtDataDTO pollRtDataDTO = new PollRtDataDTO();
        pollRtDataDTO.setBeginTime(beginTime);
        pollRtDataDTO.setEndTime(endTime);
        pollRtDataDTO.setIdList(monitorSiteList);
        List<PollHourEntity> pollHourEntities = pollHourService.queryByTimeAndMonitorList(pollRtDataDTO);
        if (CollectionUtil.isEmpty(pollHourEntities)){
            // 数据为空直接返回
            return true;
        }
        JSONObject sumO = new JSONObject();
        Double wqiValue = getWqiValue(pollHourEntities, sumO);

        // 保存数据
        // 时
        cal.set(Calendar.HOUR_OF_DAY, 0);
        // 分
        cal.set(Calendar.MINUTE, 0);
        // 秒
        cal.set(Calendar.SECOND, 0);
        // 毫秒
        cal.set(Calendar.MILLISECOND, 0);
        saveWQI(sumO, wqiValue, cal.getTime(), OmConstant.DATA_TYPE_DAY);

        return true;
    }

    @Override
    public Boolean calculateWQIHourHandler() {
        // 查询WQI站点
        LambdaQueryWrapper<PollMonitorSiteEntity> wrapper = new LambdaQueryWrapper<>();
        List<Long> monitorSiteList = pollMonitorSiteService.list(wrapper)
                .stream()
                .map(PollMonitorSiteEntity::getId)
                .distinct().collect(Collectors.toList());
        if (CollectionUtil.isEmpty(monitorSiteList)) {
            // 没有WQI站点直接返回
            return true;
        }
        Calendar cal = Calendar.getInstance();
        Date endTime = cal.getTime();
        cal.add(Calendar.HOUR_OF_DAY, -1);
        Date beginTime = cal.getTime();
        PollRtDataDTO pollRtDataDTO = new PollRtDataDTO();
        pollRtDataDTO.setBeginTime(beginTime);
        pollRtDataDTO.setEndTime(endTime);
        pollRtDataDTO.setIdList(monitorSiteList);

        List<PollMinEntity> pollMinEntities = pollMinService.queryByTimeAndMonitorList(pollRtDataDTO);
        if (CollectionUtil.isEmpty(pollMinEntities)){
            // 数据为空直接返回
            return true;
        }
        JSONObject sumO = new JSONObject();
        Double wqiValue = getWqiValue(pollMinEntities, sumO);

        // 保存数据
        cal.setTime(endTime);
        cal.set(Calendar.MINUTE, 0);
        saveWQI(sumO, wqiValue, cal.getTime(), OmConstant.DATA_TYPE_HOUR);

        return true;
    }

    private void saveWQI(JSONObject sumO, Double wqiValue, Date time, Integer dataType) {
        // wqi值的范围
        LambdaQueryWrapper<PollWqiEntity> query = Wrappers.lambdaQuery();
        query.eq(PollWqiEntity::getLevel, wqiValue);
        PollWqiEntity wqiEntity = pollWqiService.getOne(query);

        // 保存WQI数据
        PollWqiDataEntity wqiData = new PollWqiDataEntity();
        wqiData.setDataType(dataType);
        wqiData.setDataTime(time);
        wqiData.setDataJson(sumO);
        wqiData.setName(wqiEntity.getName());
        wqiData.setLevel(wqiEntity.getLevel());
        wqiData.setColor(wqiEntity.getColor());
        baseMapper.insert(wqiData);
    }

    private Double getWqiValue(List<? extends BaseOmDataEntity> baseOmDataEntities, JSONObject sumO) {
        for (BaseOmDataEntity baseOmDataEntity : baseOmDataEntities) {
            JSONObject dataJson = baseOmDataEntity.getDataJson();
            // 只需要WQI计算需要的因子
            JSONObject data = new JSONObject();
            for (String s : PollFactorConstant.WQIcode) {
                data.put(s, dataJson.get(s));
            }
            pollRtDataHisService.handleCalculateWQITask(data, sumO, "val");
        }
        Map<String, PollFactorInfoEntity> map = pollFactorInfoService.list().stream().collect(Collectors.groupingBy(PollFactorInfoEntity::getCode,
                Collectors.collectingAndThen(Collectors.toList(), value -> value.get(0))));
        // val求平均
        for (String s : sumO.keySet()) {
            JSONObject factorO = sumO.getJSONObject(s);
            double avg = factorO.getDoubleValue("val") / factorO.getDoubleValue("factorNum");
            factorO.put("val", Double.valueOf(String.format("%.2f", avg)));
            PollFactorInfoEntity pollFactorInfoEntity = map.get(s);
            if (ObjectUtil.isNotNull(pollFactorInfoEntity)) {
                factorO.put("name", Optional.ofNullable(pollFactorInfoEntity.getName()).orElse(""));
                factorO.put("unit", Optional.ofNullable(pollFactorInfoEntity.getUnit()).orElse(""));
            }

        }
        Aqi wqi = pollRtDataHisService.calculateWQI(sumO);
        JSONObject wqiO = new JSONObject();
        Double wqiValue = wqi.getAqi();
        wqiO.put("val", wqiValue);
            wqiO.put("name", "WQI");
        sumO.put("WQI", wqiO);
        return wqiValue;
    }
}
